package exteditapp;

/**
 * Implements application loop.
 * 
 * This iterator every certain amout of time invokes currents application state's handle method.
 * Well, actually it's makes certain "sleeping" time between invocations.
 * @author Arturas Smorgun, arturas@smorgun.lt
 * @version 2009.04.22
 */
public class AppletIterator implements Runnable {

	/**
	 * Throw this interface we communicate with system module.
	 */
	protected IController controller;
	
	/**
	 * System module
	 */
	protected IModuleApplet module;
	
	/**
	 * How often cycle will iterate (one iteration in N milliseconds).
	 */
	protected static int frequency = 100;
	
	/**
	 * Period of cycling (number of iteration a second).
	 */
	protected static int period = 1000/frequency;
	
	/**
	 * Lifetime counter. Counts amount of cycles made.
	 */
	protected int counter = 0;
	
	/**
	 * Default constructor. Also sets controller value
	 * @param controller controller throw which we control system module and view
	 */
	public AppletIterator(IController controller){
		this.controller = controller;                   
		this.module = controller.getModule();
	}

	/**
	 * Iterate program actions every n milliseconds
	 */
	protected void iterate() {
		this.counter = 0;
		while(true){
			try{
				//if editor not started, or only downloading smething - this doesnt counts.
				this.increaseLifetime();
				this.module.getWorkingFile().getCurrentState().handle();
				this.module.notifyListeners();
				Thread.sleep(frequency);
				
				if(this.counter % this.period == 0)
					this.module.getWorkingFile().getCurrentState().getAction().updateText(this.getLifetime());
			}
			catch(InterruptedException e){
				Runtime.getRuntime().gc();
				Runtime.getRuntime().runFinalization();
				return;
			}
		}
	}

	/**
	 * This method is for execution of program iteration in separated thread
	 */
	public void run() {
		this.iterate();
	}

	/**
	 * Returns current iterator lifetime counter (in seconds, but not precise)
	 * @return iterator lifetime counter (in seconds, but not precise)
	 */
	public synchronized int getLifetime(){
		return this.counter/ period;
	}
	
	/**
	 * Increase lifetime counter.
	 */
	protected synchronized void increaseLifetime(){
		this.counter++;
	}
	
}
